﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using DG.Tweening;
using ZGameFramework;

public enum FlyType
{
    Tween,
    Bezier,
    Velocity,
}

public class FlyTweenEase
{
    public static List<Ease> unableEase = new List<Ease>() {
        Ease.Unset,// = 0,
        Ease.Linear ,
        Ease.InSine ,
        Ease.OutSine ,
        Ease.InOutSine ,
        Ease.InQuad ,
        Ease.OutQuad ,
        Ease.InOutQuad ,
        Ease.InCubic,
        Ease.OutCubic ,
        Ease.InOutCubic ,
        Ease.InQuart,
        Ease.OutQuart ,
        Ease.InOutQuart,
        Ease.InQuint,
        Ease.OutQuint ,
        Ease.InOutQuint,
        Ease.InExpo ,
        Ease.OutExpo ,
        Ease.InOutExpo ,
        Ease.InCirc,
        Ease.OutCirc ,
        Ease.InOutCirc ,
        //Ease.InElastic ,
        //Ease.OutElastic ,
        //Ease.InOutElastic ,
        Ease.InBack ,
        Ease.OutBack ,
        Ease.InOutBack,
        //Ease.InBounce,
        //Ease.OutBounce ,
        //Ease.InOutBounce ,
        Ease.Flash,
        Ease.InFlash ,
        Ease.OutFlash,
        Ease.InOutFlash ,
    };

    public Ease GetRandomEase() { return unableEase[Random.Range( 0, unableEase.Count)]; }
}

public class FlyPlayer: IReference
{
    public long LogicID;

    public Transform transform;

    public FlyType flyType = FlyType.Tween;

    public bool m_isActive = false;

    public Vector3 realPosition = Vector3.zero;
    public Vector3 position = Vector3.zero;
    public Vector3 from = Vector3.zero;
    public Vector3 to = Vector3.zero;
    public Vector3 velocity = Vector3.zero;

    //跟随
    public bool m_followTarget = false;
    public Transform tTarget;
    public Vector3 startTargetPosition = Vector3.zero;

    // Scale
    public bool m_followScale = false;
    public float fromScale = 1;
    public float toScale = 1;

    // Rotate
    public bool m_followRotate = false;
    public float rotateSpeed  = 500;
    public Vector3 rotateEuler = Vector3.right;

    // Physics
    public bool m_followPhysics = false;

    //Bezier
    public Vector3 center;

    public float physics_G = Physics_G;

    //Tween 
    private Vector3 TweenGetter() { return position; }
    private void TweenSetter(Vector3 _position) { position = _position; }

    //相对坐标
    public bool m_IsLocalPosition =false;

    //设置时间曲线
    private AnimationCurve m_TimeAnimationCurve = null;
    private bool m_IsTimeEase = false;
    private float realTime = 0;

    public float time = 0;
    public float speed = 1.0f;

    public System.Action onUpdate { get; set; }
    public System.Action onComplete { get; set; }

    public static float Physics_G = 15.0f;

    private Vector3 TranPosition {
        get
        {
            if ( m_IsLocalPosition )
            {
                return transform.localPosition;
            }
            else
            {
                return transform.position;
            }
        }
        set
        {
             if ( m_IsLocalPosition )
            {
                transform.localPosition = value;
            }
            else
            {
                transform.position = value;
            }
        }
    }

    public void Clear()
    {
        LogicID = 0;
        time = 0;
        transform = null;
        tTarget = null;
        m_isActive = false;
        m_followTarget = false;
        m_followScale = false;
        m_followRotate = false;
        m_IsLocalPosition = false;

        m_IsTimeEase = false;
        m_TimeAnimationCurve = null;
        realTime = 0;

        onUpdate = null;
        onComplete = null;

    }

    public void Init(long logicID, Transform _transform, Vector3 p1, Vector3 p2, float duration, float disRatio, float heightRatio, float angle = 0)
    {
        LogicID = logicID;
        transform = _transform;

        from = p1;
        to = p2;
        speed = 1.0f / duration;

        position = p1;
        center = BezierCurveTools.CalculateCenterPoint( p1, p2, disRatio, heightRatio, angle );

        time = 0;
        flyType = FlyType.Bezier;
        m_isActive = true;
    }

    public void Init(long logicID, Transform _transform, Vector3 p1, Vector3 p2, float duration, Vector2 _center)
    {
        LogicID = logicID;
        transform = _transform;

        from = p1;
        to = p2;
        speed = 1.0f / duration;

        position = p1;
        center = _center;

        time = 0;
        flyType = FlyType.Bezier;
        m_isActive = true;
    }

    public void Init(long logicID, Transform _transform, Vector3 p1, Vector3 p2, float duration, Ease ease = Ease.Linear)
    {
        LogicID = logicID;
        transform = _transform;

        from = p1;
        to = p2;
        speed = 1.0f / duration;

        DOTween.To(TweenGetter, TweenSetter, to, duration).SetEase(ease);


        time = 0;
        flyType = FlyType.Tween; 
        m_isActive = true;
    }

    public void Init(long logicID, Transform _transform, Vector3 v, float duration)
    {
        LogicID = logicID;
        transform = _transform;

        speed = 1.0f / duration;
        velocity = v;

        time = 0;
        flyType = FlyType.Velocity;
        m_isActive = true;
    }

    public void SetFollowTarget( Transform _tTarget )
    {
        tTarget = _tTarget;
        startTargetPosition = tTarget.position;

        m_followTarget = true;
    }

    public void SetFollowScale(float _fromScale, float _toScale)
    {
        fromScale = _fromScale;
        toScale = _toScale;

        m_followScale = true;
    }

    public void SetFollowRotate( float _rotateSpeed)
    {
        rotateEuler = Vector3.Cross(Vector3.down, (from - to).normalized);
        rotateSpeed = _rotateSpeed;


        m_followRotate = true;
    }

    public void SetFollowPhysics( float _physics_G = 15.0f)
    {
        physics_G = _physics_G;
        m_followPhysics = true;

    }

    public void SetLocalPosition()
    {
        m_IsLocalPosition = true;
    }

    public void SetTimeCurve(AnimationCurve curve)
    {
        m_IsTimeEase = true;
        m_TimeAnimationCurve = curve;
        realTime = 0;
    }

    public void OnLateUpdate(float deltaTime)
    {
        if (m_isActive)
        {
            if (!m_IsTimeEase){
                time += deltaTime * speed;
            }
            else {
                realTime += deltaTime * speed;
                time = m_TimeAnimationCurve.Evaluate( realTime );
            }

            if (time < 1)
            {
                switch (flyType)
                {
                    case FlyType.Tween:
                        OnUpdateImpTween(deltaTime);
                        break;
                    case FlyType.Bezier:
                        OnUpdateImpBezier(deltaTime);
                        break;
                    case FlyType.Velocity:
                        OnUpdateImpVelocity(deltaTime);
                        break;
                }

                if ( m_followTarget && null != tTarget) { realPosition = position + (tTarget.position - startTargetPosition) * time; }
                else { realPosition = position; }

               

                if (null != transform)
                {
                    TranPosition = realPosition;
                    if (m_followScale) { transform.localScale = Mathf.Lerp(fromScale, toScale, time) * Vector3.one; }
                    if (m_followRotate) {
                        transform.Rotate( rotateEuler * rotateSpeed * deltaTime, Space.Self); 
                    }
                }

                if (null != onUpdate) { onUpdate(); }
            }
            else
            {
                if (null != transform)
                {
                    if (m_followTarget)
                    {
                        realPosition = to + (tTarget.position - startTargetPosition);
                        TranPosition = realPosition;
                    }
                    else { TranPosition = to; }
                    if (m_followScale) { transform.localScale = toScale * Vector3.one; }
                }

                m_isActive = false;
                if (null != onComplete) { onComplete(); }  
            }
        }
    }

    private void OnUpdateImpTween(float deltaTime)
    {
       
    }
    private void OnUpdateImpBezier(float deltaTime)
    {
        position = BezierCurve.Bezier(from, center, to, time);
    }
    private void OnUpdateImpVelocity(float deltaTime)
    {
        position = TranPosition + velocity * deltaTime;
        to = position;

        if (m_followPhysics) { velocity.y -= physics_G * deltaTime; }
        if (velocity.y <= 0) { time = 1; }
    }

    
}

